package com.vogue.flowmeter.profile.data;

import android.util.Log;

import com.vogue.flowmeter.util.ConvertUtils;
import java.math.BigInteger;

import no.nordicsemi.android.ble.data.Data;

/**
 * 写指令 协议封装
 */
public class VogueBleWriteData {

    //设备写操作
    //写设备PID
    private static final int WRITE_EQUIPMENT_PID = 0x90;
    //写设备卡号
    private static final int WRITE_SYSTEM_CARD_NUMBER = 0x94;
    //写设备MasterIP
    private static final int WRITE_EQUIPMENT_MASTERIP = 0x95;
    //写SubIP
    private static final int WRITE_EQUIPMENT_SUBIP = 0x96;

    //时间类写操作
    //写采样周期
    private static final int WRITE_SAMPLING_PERIOD = 0xa0;
    //写发送周期
    private static final int WRITE_SENDING_PERIOD = 0xa1;
    //写日历时钟
    private static final int WRITE_CALENDAR_CLOCK = 0xa2;


    //写远端强制常规发送
    private static final int REMOTE_MANDATORY_NORMAL_SEND = 0xc0;
    //主设备升级指令
    private static final int MASTER_EQUIPMENT_UPGRADE = 0xe0;
    //从设备升级指令
    private static final int SLAVE_EQUIPMENT_UPGRADE = 0xe1;
    //外部参数设置
    private static final int EXTERNAL_PARAMETERS = 0xea;
    //系统重启
    private static final int SYSTEM_RESTART = 0x0a;

    //读外接水表水量
    private static final int READ_METER_WATER_QUANTITY = 0x51;

    //测试指令
    private static final int WRITE_200_TEST = 0xf4;
    /**
     * 测试200指令
     * @param msg
     * @return
     */
    public static Data Write200TEST(String msg) {
        return new Builder().setControl(WRITE_200_TEST).setData(msg,1).builder();
    }

    /**
     * 读外接水表水量
     * @param msg
     * @return
     */
    public static Data ReadMeterWaterQuantity(String msg) {
        return new Builder().setControl(READ_METER_WATER_QUANTITY).setData(msg,1).builder();
    }

    /**
     * 系统重启
     * @param msg
     * @return
     */
    public static Data SystemRestart(String msg) {
        return new Builder().setControl(SYSTEM_RESTART).setData(msg,1).builder();
    }
    /**
     * 写设备PID
     *
     * @param msg
     * @return
     */
    public static Data WriteEquipmentPid(String msg) {
        return new Builder().setControl(WRITE_EQUIPMENT_PID).setData(msg,1).builder();
    }

    /**
     * 写设备卡号
     *
     * @param msg
     * @return
     */
    public static Data WriteSystemCardNumber(String msg) {
        return new Builder().setControl(WRITE_SYSTEM_CARD_NUMBER).setData(msg,1).builder();
    }

    /**
     * 写设备MasterIP
     *
     * @param msg
     * @return
     */
    public static Data WriteEquipmentMasterIp(String msg) {
        return new Builder().setControl(WRITE_EQUIPMENT_MASTERIP).setData(msg,1).builder();
    }

    /**
     * 写设备SubIP
     *
     * @param msg
     * @return
     */
    public static Data WriteEquipmentSubIp(String msg) {
        return new Builder().setControl(WRITE_EQUIPMENT_SUBIP).setData(msg,1).builder();
    }

    /**
     * 写采样周期
     *
     * @param msg
     * @return
     */
    public static Data WriteSamplingPeriod(String msg) {
        return new Builder().setControl(WRITE_SAMPLING_PERIOD).setData(msg,2).builder();
    }

    /**
     * 写发送周期
     *
     * @param msg
     * @return
     */
    public static Data WriteSendingPeriod(String msg) {
        return new Builder().setControl(WRITE_SENDING_PERIOD).setData(msg,2).builder();
    }

    /**
     * 写日历时钟
     *
     * @param msg
     * @return
     */
    public static Data WriteCalendarClock(String msg) {
        return new Builder().setControl(WRITE_CALENDAR_CLOCK).setData(msg,3).builder();
    }

    /**
     * 写远端强制常规发送
     *
     * @param msg
     * @return
     */
    public static Data RemoteMandatoryNormalSend(String msg) {
        return new Builder().setControl(REMOTE_MANDATORY_NORMAL_SEND).setData(msg,1).builder();
    }

    /**
     * 主设备升级
     *
     * @param msg
     * @return
     */
    public static Data MasterEquipmentUpgrade(String msg) {
        return new Builder().setControl(MASTER_EQUIPMENT_UPGRADE).setData(msg,1).builder();
    }

    /**
     * 从设备升级
     *
     * @param msg
     * @return
     */
    public static Data SlaveEquipmentUpgrade(String msg) {
        return new Builder().setControl(SLAVE_EQUIPMENT_UPGRADE).setData(msg,1).builder();
    }

    /**
     * 外部参数设置
     *
     * @param msg
     * @return
     */
    public static Data ExternalParameters(String msg, String address) {
        switch (address) {
            case "0060":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0061":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;

            case "0071":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0072":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0073":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0074":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0075":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;

            case "0033":
                msg = ConvertUtils.numToHex32(Integer.valueOf(msg));
                break;
            case "0035":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;

            case "0036":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            case "0037":
                msg = ConvertUtils.numToHex16(Integer.valueOf(msg));
                break;
            default:
                msg = ConvertUtils.numToHex32(Float.floatToIntBits(Float.valueOf(msg)));
        }

        String data = address + msg;

        return new Builder().setControl(EXTERNAL_PARAMETERS).setData(data,4).builder();
    }

    /**
     * 协议构造器
     */
    public static class Builder {

        //帧头
        private String header;
        //设备标识
        private String identification;
        //传输方向
        private String direction;
        //地址
        private String address;
        //加密版本
        private String encryption;
        //控制字
        private String control;
        //数据长度
        private String dataLength;
        //数据
        private String data;
        //校验和
        private String checksum;
        //帧尾
        private String end;


        public Builder() {
            Builder();
        }

        private Builder Builder() {

            this.header = Integer.toHexString(0x68);
            this.identification = Integer.toHexString(0x62) + Integer.toHexString(0x74);
            this.direction = Integer.toHexString(0xaa);
            this.address = Integer.toHexString(0xff);
            this.encryption = "00";
            this.end = Integer.toHexString(0x16);

            return this;
        }

        public Builder setControl(int command) {
            this.control = String.format("%02x", command);
            return this;
        }

        /**
         * 设置数据
         * @param msg 写入的数据
         * @param type 不同数据类型 1.普通hex  2.short  3.bcd  4.普通外置
         * @return
         */
        public Builder setData(String msg,int type) {
            this.dataLength = String.format("%04x", msg.length());

            switch (type){
                case 1:
                    this.data = ConvertUtils.str2HexStr(msg);
                    break;
                case 2:
                    this.dataLength="0002";
                    this.data = String.format("%04d", Integer.parseInt(msg));
                    break;
                case 3:
                    //同步时钟
                    this.dataLength="0006";
                    this.data = String.format("%012d", BigInteger.valueOf(Long.valueOf(msg)));
                    break;
                case 4:
                    this.data = ConvertUtils.str2HexStr(msg);
                    break;
                default:

            }

            Log.e("Builder","dataLength: "+dataLength+"  data："+data);

            String bleData = header + identification + direction + address + encryption + control + dataLength + data;
            this.checksum = checkSum(bleData);
            return this;
        }

        public Data builder() {
            String read = header + identification + direction + address + encryption + control + dataLength + data + checksum + end + "\\r\\n";
            return Data.from(read);
        }

        private String checkSum(String data) {

            Log.e("checkSum", data + " write " + ConvertUtils.makeCheckSum(data));

            return ConvertUtils.makeCheckSum(data);
        }

    }

}
